
/**
* @file char.c
* @brief 用于buffer读写的字符设备
* @author zshare
* @version v1.0
* @date 2022-02-13
* @history  
*/

#include <linux/module.h>//对应内核源码中include/linux/module.h
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/init.h>	//包含了module_init和module_exit的声明
#include <linux/cdev.h>	//包含字符设备操作函数
#include <linux/fs.h>	//包含文件接口操作函数
#include <linux/uaccess.h>	//
#include <asm/atomic.h>
#include <linux/slab.h>

#define _log_
#ifdef _log_
	#define kernel_print(format, arg...) printk(format,## arg)
#else
	#define kernel_print(format, arg...) do{}while(0)
#endif
#define VERSION "V1.0"
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
#define nil NULL
#define CMD_GET_VERSION 0x01

struct cdev *cdev = nil;//字符设备指针
dev_t devno;//设备号
const u32 dev_count = 64;//设备数量

typedef struct{

};

loff_t tchar_llseek(struct file *file, loff_t off, int whence){
	return 0;
}

ssize_t tchar_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos){
	u8 *pdata = filp->private_data;
	if(pdata == nil){ return 0; }
	copy_to_user(buffer, pdata, count);//从内核空间将数据拷贝到用户空间
	return count;
}

ssize_t tchar_write(struct file *filp, const char __user *buffer, size_t count, loff_t *ppos){
	u8 *pdata = filp->private_data;
	if(pdata == nil){ return 0; }
	copy_from_user(pdata, buffer, count);//从用户空间将数据拷贝到内核空间
	return count;
}

int tchar_open(struct inode *inode, struct file *filp){
	//申请一块数据buffer
	u8 *buffer = kzalloc(1024, GFP_ATOMIC);
	if(buffer == nil){ return -1; }
	filp->private_data = buffer;
	return 0;
}

int tchar_release(struct inode *inode, struct file *filp){
	//释放缓存
	if(filp->private_data){ kfree(filp->private_data); }
	return 0;
}

long sis_vsm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	switch(cmd){
		case CMD_GET_VERSION://获取版本,把版本号拷贝给用户空间
			copy_to_user((u8 *)arg, VERSION, strlen(VERSION));
		break;
	}
	return 0;
}

static const struct file_operations tchar_fops = {
	.open = tchar_open,
	.release = tchar_release,
	.read = tchar_read,
	.write = tchar_write,
	.llseek = tchar_llseek,
	.unlocked_ioctl = sis_vsm_ioctl,
	.owner = THIS_MODULE,
};


static int __init char_init(void){
	int ret = -1;

	//1,动态申请设备号,次设备号基数为0申请64个次设备
	ret = alloc_chrdev_region(&devno, 0, dev_count, "tchar");
	if(ret < 0){ return ret; }
	//2,申请一个字符设备
	cdev = cdev_alloc();
	if(cdev == nil){ unregister_chrdev_region(devno, dev_count); return -1; }//失败后不要忘记释放之前申请的设备号
	//3,绑定文件操作
	cdev_init(cdev, &tchar_fops);
	//4,添加进系统
	ret = cdev_add(cdev, devno, dev_count);
	if(ret < 0){ 
		cdev_del(cdev);
		unregister_chrdev_region(devno, dev_count); 
		cdev = nil;
	}
	kernel_print("tchar device init done.\n");
	return ret;
}

static void __exit char_exit(void){
	if(cdev){ cdev_del(cdev); }
	unregister_chrdev_region(devno, dev_count); 
	kernel_print("tchar device exit done.\n");
}

module_init(char_init);
module_exit(char_exit);

MODULE_LICENSE("GPL");//软件代码接受的许可协议General Public License
MODULE_AUTHOR("Share");//声明作者
MODULE_DESCRIPTION("A buffer char module");//模块简单的描述
MODULE_VERSION(VERSION);//模块版本
MODULE_ALIAS("route");//模块在用户空间的别名






















